// SpinTestResults.h: interface for the CSpinTestResults class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SPINTESTRESULTS_H__C53BE20A_E707_4DBD_8FFD_C3C318BCB3CC__INCLUDED_)
#define AFX_SPINTESTRESULTS_H__C53BE20A_E707_4DBD_8FFD_C3C318BCB3CC__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "..\SpinTestMessage.h"

class CSpinTestResults
{
public:
	CSpinTestResults();
	virtual ~CSpinTestResults();

	bool Initialize( CSession* pSession, UINT nSlotGutID );

	DWORD GetBetPerLine() const;
	void SetBetPerLine( DWORD nBetPerLine );

	void Reset();
	
	void Serialize( CArchive& ar );

	int GetNumGameModes() const;
	int GetNumPayoutTypes() const;
	int GetNumBonusGameTypes() const;

	__int64 GetPaidLinesPlayed() const;
	__int64 GetFreeLinesPlayed() const;
	__int64 GetTotalLinesPlayed() const;

	__int64 GetTotalBet() const;

	__int64 GetGameModePayout( int nGameMode ) const;
	double GetGameModePayoutPercent( int nGameMode ) const;

	__int64 GetBonusGameTypePayout( int nBonusGameType ) const;
	double GetBonusGameTypePayoutPercent( int nBonusGameType ) const;

	__int64 GetProgressivePayout() const;
	double GetProgressivePayoutPercent() const;

	__int64 GetTotalPayout() const;
	double GetTotalPayoutPercent() const;

	__int64 GetExpectedTotalPayout() const;
	double GetExpectedTotalPayoutPercent() const;

	double GetTrueStandardDeviation() const;
	double GetTrueVariance() const;

	double GetExpectedStandardDeviation() const;
	double GetExpectedVariance() const;

	double GetStandardDeviation() const;
	double GetVariance() const;

	class CConfidenceInterval
	{
	public:
		CConfidenceInterval()
		{
			m_dConfidenceLevel = 0;
			m_dMinValue = 0;
			m_dMaxValue = 0;
		}

		double m_dConfidenceLevel;
		double m_dMinValue;
		double m_dMaxValue;
	};

	typedef CArray< CConfidenceInterval, CConfidenceInterval& > CConfidenceIntervalArray;

	void GetConfidenceIntervals( CConfidenceIntervalArray& a ) const;

	enum PAYOUT_WITHIN_RANGE
	{
		pwrYes,
		pwrWarning,
		pwrNo
	};

	PAYOUT_WITHIN_RANGE IsPayoutWithinExpectations() const;

	double GetSamplingDistribution() const;
	double GetStandardNormalCumulativeDistribution() const;
	double GetZOfCostly() const;
	double GetPOfCostly() const;

	void AccumulateResults( const CSpinTestResults* pResults );
	void AccumulateResults( const CSpinTestSummaryDataMessage* pMsg );
	void AccumulateResults( BYTE byGameMode, const CSpinTestGameModeSummaryDataMessage* pMsg );
	void AccumulateResults( BYTE byGameMode, BYTE byPayoutType, const CSpinTestPayoutTypeDetailDataMessage* pMsg );
	void AccumulateResults( BYTE byBonusGameType, const CSpinTestBonusGameTypeDetailDataMessage* pMsg );

	class CDetailData
	{
	public:
		CDetailData();

		void Reset();

		// The number of times that this payout type or bonus game type hit.
		__int64 m_nHits;

		// The total payout for this payout type or bonus game type.
		__int64 m_nTotalPayout;
	};

	class CGameModeResults
	{
	public:
		CGameModeResults();

		void Reset();

		const CDetailData& GetPayoutDataNoSubst( int nIndex ) const;
		CDetailData& GetPayoutDataNoSubst( int nIndex );

		const CDetailData& GetPayoutDataWithSubst( int nIndex ) const;
		CDetailData& GetPayoutDataWithSubst( int nIndex );

		// The total payout for this game mode.
		__int64 m_nTotalPayout;

		// The number of times this game mode was triggered.
		__int64 m_nNumTriggers;

		// An array of detail data objects used to accumulate results when the
		// payout did not have a substitution.
		CArray< CDetailData, CDetailData& > m_aPayoutDataNoSubst;

		// An array of detail data objects used to accumulate results when the
		// payout did have a substitution.
		CArray< CDetailData, CDetailData& > m_aPayoutDataWithSubst;
	};

	const CGameModeResults& GetGameModeResults( int nIndex ) const;
	const CDetailData& GetBonusGameData( int nIndex ) const;

private:
	BYTE LoadMachineID(  CSession* pSession, UINT nSlotGutID );
	bool LoadMaxGameModeID( CSession* pSession, BYTE byMachineID );
	bool LoadMaxPayoutTypeID( CSession* pSession, UINT nSlotGutID );
	bool LoadMaxBonusGameType( CSession* pSession, UINT nSlotGutID );
	bool LoadExpectedResults( CSession* pSession, UINT nSlotGutID );

	CGameModeResults& GetGameModeResults( int nIndex );
	CDetailData& GetBonusGameData( int nIndex );

	// The total amount of money bet during the batch of spins, in base currency
	// units (pennies for USD).
	__int64 m_nTotalBet;

	// The bet per line that is always used in each batch of spins.  This is
	// needed so that we can properly scale the payouts during statistical
	// analysis.
	DWORD m_nBetPerLine;

	// The total payout during the batch of spins in base currency units,
	// including the payout from every game mode and from progressives.
	__int64 m_nTotalPayout;

	// The sum of the payouts squared for each paid game.  Used to calculate the true
	// standard deviation of the sample spins.
	double m_dSumPayoutsSquared;

	// The total payout from progressives during the batch of spins, in base
	// currency units.
	__int64 m_nTotalProgressivePayout;

	// The total number of lines played during the batch of spins, including
	// both paid lines and free lines.
	__int64 m_nTotalLinesPlayed;

	// The total number of paid lines played during the batch of spins.
	__int64 m_nPaidLinesPlayed;

	// The total number of free lines played during the batch of spins.
	__int64 m_nFreeLinesPlayed;

	CArray< CGameModeResults, CGameModeResults& > m_aGameModeResults;

	// An array of detail data objects used to accumulate results for each
	// bonus game type.
	CArray< CDetailData, CDetailData& > m_aBonusGameData;

	// The expected standard deviation from the submission sheet.
	double m_dExpectedStandardDeviation;

	// The expected payout from the submission sheet.
	double m_dExpectedTotalPayout;
};

template <>
void AFXAPI SerializeElements< CSpinTestResults::CGameModeResults >( CArchive& ar, CSpinTestResults::CGameModeResults* pElements, int nCount );

#endif // !defined(AFX_SPINTESTRESULTS_H__C53BE20A_E707_4DBD_8FFD_C3C318BCB3CC__INCLUDED_)
